/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package taskmanager;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Date;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Pavel
 */
public class Controller {
    private StorageFactory storageFactory;
    private AlarmManagerFactory alarmManagerFactory;
    private TaskManager taskManager;
    private TaskMonitor taskMonitor;
    private List<TaskInfo> taskList;
    private Storage storage;
    private boolean mustUpdateTable = false;
    private int period = 1000;
    
    
    /**Gets period of checking task list
     * 
     * 
     * @return period of checking task list
     */
    public int getPeriod(){
        return period;
    }
    
    /**Constructor
     * 
     */
    public Controller(){
        storageFactory = new XMLStorageFactory();
        alarmManagerFactory = new SimpleAlarmManagerFactory();
        
        storage = storageFactory.createInstance();
        AlarmManager alarmManager = alarmManagerFactory.createInstance();
        taskList = storage.loadAll();
        
        taskManager = new TaskManager(taskList);
        
        taskMonitor = new TaskMonitor(taskList, alarmManager, this);
        Thread monitor = new Thread(taskMonitor);
        monitor.start();
    }
    
    /**
     *
     * @return Information about done and remaining tasks
     * 
     *
     */

    public StatisticInfo calculateStatistics() {
        return taskManager.calculateStatistics();
    }

    /**Edits parameters of task if they are different
     * 
     * @param id       Task id
     * @param name      Task name
     * @param description      Task decription
     * @param contacts       Task contacts
     * @param dueDate      Task due date
     *
     */
    public void editTask(int id,String name, String description, String contacts, Date dueDate){ 
        if (name == "")
            name = "<no name>";
        taskManager.editTask(id, name, description, contacts, dueDate);
    }
    
    /**Set status "done" for the task
     * 
     * @param id       Task id      
     *
     */
    public void closeTask(int id){
        taskManager.closeTask(id);
    }
   
    /**Creates new task
     * 
     * @param name      Task name
     * @param description      Task decription
     * @param contacts       Task contacts
     * @param dueDate      Task due date
     * 
     * @return Creared task
     */
    public TaskInfo createTask(String name, String description, String contacts, Date dueDate) {
        if (name == "")
            name = "<no name>";
        return taskManager.createTask(name, description, contacts, dueDate);
    }
    
    /**Get list of tasks
     * 
     * @return Pointer for list of tasks
     */
    public List<TaskInfo> getAll() {
        return taskManager.getAll();
    }

    /**Removes specified task
     * 
     * @param id     Task ID
     */
    public void removeTask(int id) {
        taskManager.removeTask(id);
    }
    
    
     /**Searches for task specified by its ID
     * 
     * @param id    Task ID
     * @return Task specified by ID
     */
    public TaskInfo findById(int id){
        return taskManager.findById(id);
    }
     
    /**Gets all tasks on the specified date
     * 
     * @param date     Specified date
     * @return Tasks on the specified date
     */
    public List tasksOnDate(Date date) {
        GregorianCalendar cl = new GregorianCalendar();
        cl.setTime(date);
        cl.set(Calendar.HOUR_OF_DAY, 0);
        cl.set(Calendar.MINUTE, 0);
        cl.set(Calendar.SECOND, 0);
        cl.set(Calendar.MILLISECOND, 0);
        Date d1 = cl.getTime();
        cl.add(Calendar.DAY_OF_YEAR, 1);
        Date d2 = cl.getTime();

        List<TaskInfo> allTasks = getAll();
        List<TaskInfo> tasksToDate = new LinkedList<TaskInfo>();
        for( TaskInfo task: allTasks){
            Date theDate = task.getDueDate();
            if (theDate.after(d1) && theDate.before(d2))
                tasksToDate.add(task);
        }
        
        return tasksToDate;
    }

    /**Checks if the date is in future
    * 
    * @param date     Specified date for checking
    * @return Result of checking if the date is in future
    */
    public boolean validateDate(Date date) {
        return taskManager.validateDate(date);
    }
    
    /**Accept changes for the storage
    *  
    * 
    */
    public void Finalize(){
        storage.saveAll(taskManager.getAll());
    }
    
    private boolean newed = false;
    
    /**
    * Sets if the table must be updated
    * @param val     Must be updated or not
    * 
    */
    public synchronized void setMustUpdate(boolean val){
        newed = true;
        this.mustUpdateTable = val;
        newed = false;
    } 
    
    /**
    * Gets if the table must be updated
    * @return    Must be updated or not
    * 
    */
    public synchronized boolean getMustUpdate(){
        while (newed)
            try {
            wait();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        boolean result = this.mustUpdateTable;
        mustUpdateTable = false;
        return result;
    }
}
